package com.markus.basic.Java多线程.生产者消费者问题;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Author:markusZhang
 * Date:Create in 2020/9/16 9:30
 * todo: 生产者消费者问题
 */
public class ProConDemo {
    ReentrantLock lock = new ReentrantLock();
    int num = 0;
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();
    public void printA() throws InterruptedException {
        try {
            lock.lock();
            if (num != 0){
                conditionA.await();
            }
            System.out.println("A");
            num = 1;
            conditionB.signal();
        }finally {
            lock.unlock();
        }
    }
    public void printB() throws InterruptedException {
        try {
            lock.lock();
            if (num != 1){
                conditionB.await();
            }
            System.out.println("B");
            num = 2;
            conditionC.signal();
        }finally {
            lock.unlock();
        }
    }
    public void printC() throws InterruptedException {
        try {
            lock.lock();
            if (num != 2){
                conditionC.await();
            }
            System.out.println("C");
            num = 0;
            conditionA.signal();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ProConDemo demo = new ProConDemo();
        Thread threadA = new Thread(new A(demo));
        Thread threadB = new Thread(new B(demo));
        Thread threadC = new Thread(new C(demo));
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
class A implements Runnable{

    ProConDemo demo;
    public A(ProConDemo demo){
        this.demo = demo;
    }

    @Override
    public void run() {
        for (int i=0;i<10;i++){
            try {
                demo.printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class B implements Runnable{
    ProConDemo demo;
    public B(ProConDemo demo){
        this.demo = demo;
    }
    @Override
    public void run() {
        for (int i=0;i<10;i++){
            try {
                demo.printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class C implements Runnable{
    ProConDemo demo;
    public C(ProConDemo demo){
        this.demo = demo;
    }
    @Override
    public void run() {
        for (int i=0;i<10;i++){
            try {
                demo.printC();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
